package cn.edu.tju.core.model;

import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;

/**
 * 虚拟钱包 - 充血模型
 * 封装核心业务逻辑
 */
@TableName("t_wallet")
public class VirtualWallet implements Serializable {
    
    @TableId(type = IdType.AUTO)
    private Long id;
    
    private Integer userId;
    
    /** 可用余额 */
    private BigDecimal balance = BigDecimal.ZERO;
    
    /** 冻结金额 */
    private BigDecimal frozenAmount = BigDecimal.ZERO;
    
    /** 透支额度 */
    private BigDecimal creditLimit = BigDecimal.ZERO;
    
    /** 已透支金额 */
    private BigDecimal overdraftAmount = BigDecimal.ZERO;
    
    /** 赠送金额（充值奖励） */
    private BigDecimal bonusAmount = BigDecimal.ZERO;
    
    /** 是否VIP: 0-否, 1-是 */
    private Integer isVip = 0;
    
    /** 钱包状态: 0-正常, 1-冻结 */
    private Integer status = 0;
    
    /** 乐观锁版本号 */
    @Version
    private Integer version = 0;
    
    @TableField(fill = FieldFill.INSERT)
    private Timestamp createdAt;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Timestamp updatedAt;
    
    // 业务方法 
    
    /**
     * 充值
     */
    public void recharge(BigDecimal amount, BigDecimal bonus) {
        validateActive();
        validateAmount(amount, "充值金额");
        validateAmount(bonus, "奖励金额");
        
        this.balance = this.balance.add(amount);
        this.bonusAmount = this.bonusAmount.add(bonus);
    }
    
    /**
     * 提现
     */
    public void withdraw(BigDecimal amount, BigDecimal fee, BigDecimal deductBonus) {
        validateActive();
        validateAmount(amount, "提现金额");
        validateAmount(fee, "手续费");
        validateAmount(deductBonus, "扣除奖励");
        
        BigDecimal totalDeduct = amount.add(fee);
        
        // 优先还透支
        if (overdraftAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal repayOverdraft = totalDeduct.min(overdraftAmount);
            overdraftAmount = overdraftAmount.subtract(repayOverdraft);
            totalDeduct = totalDeduct.subtract(repayOverdraft);
        }
        
        // 扣除余额
        if (totalDeduct.compareTo(balance) > 0) {
            throw new IllegalStateException("余额不足");
        }
        balance = balance.subtract(totalDeduct);
        
        // 扣除赠送金额
        if (deductBonus.compareTo(bonusAmount) > 0) {
            throw new IllegalStateException("赠送金额不足");
        }
        bonusAmount = bonusAmount.subtract(deductBonus);
    }
    
    /**
     * 支付
     */
    public void pay(BigDecimal amount) {
        validateActive();
        validateAmount(amount, "支付金额");
        
        BigDecimal available = getAvailableAmount();
        if (amount.compareTo(available) > 0) {
            throw new IllegalStateException("可用余额不足（含透支额度）");
        }
        
        // 优先使用余额
        if (amount.compareTo(balance) <= 0) {
            balance = balance.subtract(amount);
        } else {
            // 余额不足，使用透支
            BigDecimal needOverdraft = amount.subtract(balance);
            balance = BigDecimal.ZERO;
            overdraftAmount = overdraftAmount.add(needOverdraft);
        }
    }
    
    /**
     * 收款
     */
    public void receive(BigDecimal amount) {
        validateActive();
        validateAmount(amount, "收款金额");
        
        // 优先归还透支
        if (overdraftAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal repay = amount.min(overdraftAmount);
            overdraftAmount = overdraftAmount.subtract(repay);
            amount = amount.subtract(repay);
        }
        
        // 剩余金额加到余额
        balance = balance.add(amount);
    }
    
    /**
     * 冻结金额
     */
    public void freeze(BigDecimal amount) {
        validateActive();
        validateAmount(amount, "冻结金额");
        
        if (amount.compareTo(balance) > 0) {
            throw new IllegalStateException("余额不足，无法冻结");
        }
        
        balance = balance.subtract(amount);
        frozenAmount = frozenAmount.add(amount);
    }
    
    /**
     * 解冻金额
     */
    public void unfreeze(BigDecimal amount) {
        validateActive();
        validateAmount(amount, "解冻金额");
        
        if (amount.compareTo(frozenAmount) > 0) {
            throw new IllegalStateException("冻结金额不足");
        }
        
        frozenAmount = frozenAmount.subtract(amount);
        balance = balance.add(amount);
    }
    
    /**
     * 扣除冻结金额（订单完成时）
     */
    public void deductFrozen(BigDecimal amount) {
        validateActive();
        validateAmount(amount, "扣除金额");
        
        if (amount.compareTo(frozenAmount) > 0) {
            throw new IllegalStateException("冻结金额不足");
        }
        
        frozenAmount = frozenAmount.subtract(amount);
    }
    
    // ========== 计算属性 ==========
    
    /**
     * 总资产 = 余额 + 冻结金额 - 透支金额
     */
    public BigDecimal getTotalAssets() {
        return balance.add(frozenAmount).subtract(overdraftAmount);
    }
    
    /**
     * 可用金额 = 余额 + 剩余透支额度
     */
    public BigDecimal getAvailableAmount() {
        BigDecimal remainingCredit = creditLimit.subtract(overdraftAmount);
        return balance.add(remainingCredit.max(BigDecimal.ZERO));
    }
    
    // 验证方法 
    
    private void validateActive() {
        if (status != 0) {
            throw new IllegalStateException("钱包已冻结");
        }
    }
    
    private void validateAmount(BigDecimal amount, String fieldName) {
        if (amount == null || amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException(fieldName + "不能为负数");
        }
    }
    
    // ========== Getters and Setters ==========
    
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public BigDecimal getBalance() {
        return balance;
    }

    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }

    public BigDecimal getFrozenAmount() {
        return frozenAmount;
    }

    public void setFrozenAmount(BigDecimal frozenAmount) {
        this.frozenAmount = frozenAmount;
    }

    public BigDecimal getCreditLimit() {
        return creditLimit;
    }

    public void setCreditLimit(BigDecimal creditLimit) {
        this.creditLimit = creditLimit;
    }

    public BigDecimal getOverdraftAmount() {
        return overdraftAmount;
    }

    public void setOverdraftAmount(BigDecimal overdraftAmount) {
        this.overdraftAmount = overdraftAmount;
    }

    public BigDecimal getBonusAmount() {
        return bonusAmount;
    }

    public void setBonusAmount(BigDecimal bonusAmount) {
        this.bonusAmount = bonusAmount;
    }

    public Integer getIsVip() {
        return isVip;
    }

    public void setIsVip(Integer isVip) {
        this.isVip = isVip;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public Timestamp getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Timestamp createdAt) {
        this.createdAt = createdAt;
    }

    public Timestamp getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Timestamp updatedAt) {
        this.updatedAt = updatedAt;
    }
}